var Promise = require('bluebird');
var request = require('request');
var error = require(_ROOT + '/app/errorLogger');
var config = require(_ROOT + '/app/config');
var parseConf = config('parse');

function baseRequest(options) {
  var def = Promise.defer();

  if (!options.json) options.json = true;
  request(options, function(err, res, body) {
    if (err) throw new Error(err);
    if (res.statusCode > 299) {
    	def.reject(Error('Https request fail. statusCode: ' + res.statusCode));
    };

    def.resolve(body);
  });

  return def.promise;
}

function create(className, values) {
	if (!className || !values) throw new Error('Cannot create db object without className or values');

  var def = Promise.defer();
  var apiPath = parseConf.restObj.create.url
    .replace('<class>', className)
    .replace('<id>', '');
  var options = {
    url: apiPath,
    method: parseConf.restObj.create.method,
    headers: parseConf.restKeys,
    body: values
  };

  baseRequest(options).then(function(res) {
    def.resolve(res);
  }).catch(Error, function(e) {
    error.log(e);
    def.reject(e);
  });
  return def.promise;
}

/*
| If no optionalId is provided, the result will return all objects
| in the target class.
*/
function read(className, optionalId) {
	if (!className) throw new Error('Cannot read db class/object without className');

	var id = optionalId || '';

	var def = Promise.defer();
	var apiPath = parseConf.restObj.read.url
		.replace('<class>', className)
		.replace('<id>', id);
	var options = {
		url: apiPath,
		method: parseConf.restObj.read.method,
		headers: parseConf.restKeys
	};
	
	baseRequest(options).then(function(res) {
		def.resolve(res);
	}).catch(Error, function(e) {
		error.log(e);
		def.reject(e);
	});
	return def.promise;
}

function update(className, id, values) {
	if (!className || !id || !values) throw new Error('Cannot update db object without className, id or values');

	var def = Promise.defer();
	var apiPath = parseConf.restObj.update.url
		.replace('<class>', className)
		.replace('<id>', id);
	var options = {
		url: apiPath,
		method: parseConf.restObj.update.method,
		headers: parseConf.restKeys,
		body: values
	};
	
	baseRequest(options).then(function(res) {
		def.resolve(res);
	}).catch(Error, function(e) {
		error.log(e);
		def.reject(e);
	});
	return def.promise;
}

function del(className, id) {
	if (!className || !id) throw new Error('Cannot delete db object without an id');

	var def = Promise.defer();
	var apiPath = parseConf.restObj.delete.url
		.replace('<class>', className)
		.replace('<id>', id);
	var options = {
		url: apiPath,
		method: parseConf.restObj.delete.method,
		headers: parseConf.restKeys
	};
	
	baseRequest(options).then(function(res) {
		def.resolve(res);
	}).catch(Error, function(e) {
		error.log(e);
		def.reject(e);
	});
	return def.promise;
}

module.exports = {
  create: create,
  read: read,
  update: update,
  delete: del,
  baseRequest: baseRequest
};
